package cn.qu.netty.boot;

import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelOption;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.codec.http.HttpObjectAggregator;
import io.netty.handler.codec.http.HttpServerCodec;

public class NettyServer {

	final static Log log = Log.createLog();

	public static NettyServer createNettyServer() {
		NettyServer nettyServer = new NettyServer();
		return nettyServer;
	}

	/**
	 * 
	 * @Description:
	 * @Author XiaoLong.Qu
	 * @DateTime 2021年8月8日 下午4:36:05
	 * @param port
	 * @param queueSize netty 线程组中的队列最大容量
	 * @throws InterruptedException
	 */
	public void start(int port, int queueSize, String[] scannerPackage) throws Exception {
		NioEventLoopGroup bossGroup = null;
		NioEventLoopGroup workerGroup = null;
		ApplicationContext applicationContext = new ApplicationContext(scannerPackage);
		HandlerMappingProvider handlerMappingProvider = new HandlerMappingProvider(applicationContext);
		FilterProvider filterProvider = new FilterProvider(applicationContext);
		try {
			ServerBootstrap bootstrap = new ServerBootstrap();
			bossGroup = new NioEventLoopGroup(1);
			workerGroup = new NioEventLoopGroup();
			ChannelFuture channelFuture = bootstrap.group(bossGroup, workerGroup).channel(NioServerSocketChannel.class)
					.option(ChannelOption.SO_BACKLOG, queueSize).childHandler(new ChannelInitializer<SocketChannel>() {
						@Override
						protected void initChannel(SocketChannel ch) throws Exception {
							ch.pipeline().addLast(new HttpServerCodec()).addLast(new HttpObjectAggregator(64 * 1024)) // 最大5mb
									.addLast(new CheckIpInboundHandler())
									.addLast(new DefaultHandler(filterProvider, handlerMappingProvider));
						}
					}).bind(port).sync();
			log.log("netty server start success : port=" + port);
			channelFuture.channel().closeFuture().sync();
		} finally {
			bossGroup.shutdownGracefully();
			workerGroup.shutdownGracefully();
		}
	}

}
